package cn.nextProject.controller;

import cn.nextProject.Utils.CommonUtils;
import cn.nextProject.entity.FormConfig;
import cn.nextProject.entity.Result;
import cn.nextProject.entity.flowable.ProcessDefinitionDTO;
import cn.nextProject.entity.flowable.TaskDTO;
import cn.nextProject.entity.req.ProcessStartReq;
import cn.nextProject.service.ProcessService;
import com.fasterxml.jackson.core.JsonProcessingException;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.IOUtils;
import org.flowable.engine.form.StartFormData;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.ClassPathResource;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.*;

@RestController
@Slf4j
public class ProcessController {

    @Autowired
    private ProcessService processService;

    /**
     * 部署流程
     * @param processName
     * @return
     */
    @GetMapping("/deployFlow")
    public Result<?> deployFlow(@RequestParam("processName") String processName){

        if (ObjectUtils.isEmpty(processName)){
            return new Result<>().fail("流程名称不存在！");
        }

        processService.deployFlow(processName);

        return new Result<>().success("部署成功！",null);
    }


    /**
     * 部署流程  (正式版)
     * @param file
     * @return
     */
    @PostMapping("/deployFlowReal")
    public Result<?> deployFlowReal(@RequestParam("file") MultipartFile file){

        if (file.isEmpty()) {
            return new Result<>().fail("部署文件不能为空！");
        }

        processService.deployFlowReal(file);

        return new Result<>().success("部署成功！",null);
    }


    /**
     * 流程启动
     * @param processStartReq
     * @return
     */
    @PostMapping("/startProcess")
    public Result<?> startProcess(@RequestBody ProcessStartReq processStartReq){

        if (ObjectUtils.isEmpty(processStartReq)){
            return new Result<>().fail("数据不能为空！");
        }

        String processKey = processStartReq.getProcessKey();
        List<String> usernameList = processStartReq.getUsernameList();

        if (ObjectUtils.isEmpty(processKey)){
            return new Result<>().fail("流程Key不存在！");
        }

        if (CollectionUtils.isEmpty(usernameList)){
            return new Result<>().fail("流程审批人不能为空！");
        }
        Map<String, Object> variables = new HashMap<>();
        variables.put("bmzg",usernameList.get(0));
        variables.put("fzr",usernameList.get(1));

        int i = processService.startProcess(processKey,  variables);

        if (i == 1){
            return new Result<>().success("启动成功！",null);
        }else{
            return new Result<>().fail("启动失败！");
        }
    }

    /**
     * 查询当前用户待办任务
     * @return
     */
//    @GetMapping("/findProcessesTask")
//    public Result<?> findProcessesTask(){
//
//        String username = CommonUtils.getToken();
//
//        if (ObjectUtils.isEmpty(username)){
//            return new Result<>().fail("用户未登录！");
//        }
//        List<TaskDTO> tasks = processService.findTask(username);
//        return new Result<>().success("查询成功！",tasks);
//    }

    /**
     * 审批通过
     * @param taskId
     * @return
     */
//    @GetMapping("/completeTask")
//    public Result<?> completeTask(@RequestParam("taskId")String taskId){
//
//        if (ObjectUtils.isEmpty(taskId)){
//            return new Result<>().fail("任务ID不能为空！");
//        }
//
//        int i = processService.completeTask(taskId);
//
//        if (i == 1){
//            return new Result<>().success("完成任务成功！",null);
//        }else{
//            return new Result<>().fail("完成任务失败！");
//        }
//    }

    /**
     * 查询流程定义列表
     * @return
     */
    @GetMapping("/findAllProcessDefinition")
    public Result<?> findAllProcessDefinition(@RequestParam("name")String name){

        List<ProcessDefinitionDTO> processDefinitions = processService.findAllProcessDefinition(name);

        return new Result<>().success("查询成功！",processDefinitions);
    }

    @GetMapping("/updateSuspended")
    public Result<?> updateSuspended(@RequestParam("processDefinitionId") String processDefinitionId){

        if (ObjectUtils.isEmpty(processDefinitionId)){
            return new Result<>().fail("流程定义ID不能为空！");
        }
        processService.updateSuspended(processDefinitionId);

        return new Result<>().success("更新成功！",null);
    }

    /**
     * 查询流程定义详情
     * @param id
     * @return
     */
    @GetMapping("/getProcessDefinitionDetail")
    public Result<?> getProcessDefinitionDetail(@RequestParam("id") String id) {
        if (ObjectUtils.isEmpty(id)) {
            return new Result<>().fail("流程定义ID不能为空！");
        }
        ProcessDefinitionDTO processDefinition = processService.findProcessDefinition(id);

        return new Result<>().success("查询成功！", processDefinition);
    }

    /**
     * 删除流程定义
     * @param processDefinitionIdList
     * @return
     */
    @PostMapping("/deleteProcessDefinition")
    public Result<?> deleteProcessDefinition(@RequestBody List<String> processDefinitionIdList) {
        if (CollectionUtils.isEmpty(processDefinitionIdList)) {
            return new Result<>().fail("流程定义ID不能为空！");
        }
        for (String processDefinitionId : processDefinitionIdList) {
            processService.deleteProcessDefinition(processDefinitionId);
        }

        return new Result<>().success("删除成功！", null);
    }

    /**
     * 查看表单
     * @param id
     * @return
     */
    @GetMapping("/getProcessForm")
    public Result<?> getProcessForm(@RequestParam("id") String id) {
        if (ObjectUtils.isEmpty(id)) {
            return new Result<>().fail("流程定义ID不能为空！");
        }
        return new Result<>().success("查询成功！", processService.getProcessForm(id));
    }

    /**
     * 查看BPMN流程图
     * @param id
     * @return
     */
    @GetMapping("/getProcessBpmn")
    public Result<?> getProcessBpmn(@RequestParam("id") String id) {
        if (ObjectUtils.isEmpty(id)) {
            return new Result<>().fail("流程定义ID不能为空！");
        }
        return new Result<>().success("查询成功！", processService.getProcessBpmn(id));
    }


    /**
     * 查询 resources/processes 下的所有流程图文件
     * @param name 流程图名称（支持模糊查询）
     * @return
     */
    @GetMapping("/getAllProcessFiles")
    public Result<?> getAllProcessFiles(@RequestParam("name") String name) {
        List<Map<String, String>> result = new ArrayList<>();

        // 获取 resources/processes 目录路径
        ClassPathResource resourceDir = new ClassPathResource("processes/");
        try {
            Path dirPath = Paths.get(resourceDir.getURI());

            if (Files.exists(dirPath) && Files.isDirectory(dirPath)) {
                // 遍历目录中的文件
                Files.list(dirPath)
                        .filter(path -> path.toString().endsWith(".bpmn") || path.toString().endsWith(".bpmn20.xml"))
                        .forEach(path -> {
                            String fileName = path.getFileName().toString();
                            String processName = fileName.replaceAll("\\.(bpmn|bpmn20\\.xml)$", "");

                            // 支持按名称模糊查询
                            if (name == null || processName.contains(name)) {
                                Map<String, String> fileInfo = new HashMap<>();
                                fileInfo.put("fileName", fileName);
                                fileInfo.put("processName", processName);
                                result.add(fileInfo);
                            }
                        });
            }
        } catch (IOException e) {
            log.error("读取流程文件失败：{}", e.getMessage());
            return new Result<>().fail("读取流程文件失败");
        }

        return new Result<>().success("查询成功！", result);
    }

    /**
     * 获取指定流程文件的 XML 内容
     * @param fileName 流程文件名称（如：leave.bpmn）
     * @return 返回 XML 字符串
     */
    @GetMapping("/getProcessFileXml")
    public Result<?> getProcessFileXml(@RequestParam("fileName") String fileName) {
        try {
            // 拼接完整路径
            ClassPathResource resource = new ClassPathResource("processes/" + fileName);

            if (!resource.exists()) {
                return new Result<>().fail("文件不存在");
            }

            // 读取文件内容为字符串
            String xmlContent = IOUtils.toString(resource.getInputStream(), StandardCharsets.UTF_8);
            return new Result<>().success("获取成功", xmlContent);
        } catch (IOException e) {
            log.error("读取流程文件失败：{}", e.getMessage());
            return new Result<>().fail("读取流程文件失败");
        }
    }

    /**
     * 上传流程文件
     * @param file
     * @return
     */
    @PostMapping("/uploadProcess")
    public Result<?> uploadProcess(@RequestParam("file") MultipartFile file) {

        if (file.isEmpty()) {
            return new Result<>().fail("上传文件不能为空！");
        }

        //查询resources/processes目录下是否有同名文件
        ClassPathResource resourceDir = new ClassPathResource("processes/");
        try {
            Path dirPath = Paths.get(resourceDir.getURI());
            if (Files.exists(dirPath) && Files.isDirectory(dirPath)) {
                // 遍历目录中的文件
                Files.list(dirPath)
                        .filter(path -> path.toString().endsWith(".bpmn") || path.toString().endsWith(".bpmn20.xml"))
                        .forEach(path -> {
                            String fileName = path.getFileName().toString();
                            String processName = fileName.replaceAll("\\.(bpmn|bpmn20\\.xml)$", "");
                        });
                if (Files.exists(dirPath.resolve(Objects.requireNonNull(file.getOriginalFilename())))) {
                    return new Result<>().fail("流程文件已存在！");
                }
                Files.copy(file.getInputStream(), dirPath.resolve(file.getOriginalFilename()));
                return new Result<>().success("上传成功！",null);
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        }

        return new Result<>().fail("上传失败！");
    }

    @GetMapping("/configureFormForProcessDefinition")
    public Result<?> configureFormForProcessDefinition(@RequestParam("processDefinitionId") String processDefinitionId,
                                                      @RequestParam("formKey") Long formKey) {
        if (ObjectUtils.isEmpty(processDefinitionId) || ObjectUtils.isEmpty(formKey)){
            return new Result<>().fail("流程定义ID或表单配置ID不能为空！");
        }
        try {
            processService.configureFormForProcessDefinition(processDefinitionId, formKey);
            return new Result<>().success("配置成功！",null);
        } catch (JsonProcessingException e) {
            log.error("配置流程表单失败：{}", e.getMessage());
            return new Result<>().fail("配置流程表单失败");
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 查询流程定义配置表单
     * @param processDefinitionId
     * @return
     * @throws JsonProcessingException
     */
    @GetMapping("/findFormForProcessDefinition")
    public Result<?> findFormForProcessDefinition(@RequestParam("processDefinitionId") String processDefinitionId) throws JsonProcessingException {
        if (ObjectUtils.isEmpty(processDefinitionId)){
            return new Result<>().fail("流程定义ID不能为空");
        }
        Map<Integer, Object> formMap = processService.findFormForProcessDefinition(processDefinitionId);
        if (ObjectUtils.isEmpty(formMap.get(0))){
            return new Result<>().success("查询成功！", formMap.get(1));
        }else{
            return new Result<>().fail(formMap.get(0).toString());
        }
    }

}
